package executors;

import java.util.ArrayList;

import objects.Command;
import objects.Event;
import objects.Result;
import objects.SortedEventList;
import test.DummyEventGenerator;

/**
 * This is a class implement the sortFunction. sorting can be done according
 * following keywords, START_DATE, END_DATE, PRIORITY, TAG can sort by multiple
 * key words However, sort wont affect the original passed in SortedEventList
 * data
 * 
 * @author JJP
 * 
 */
public class SortExecutor {

	public static Result execute(Command command, SortedEventList data,
			SortedEventList completeTasks) {
		ArrayList<String> sortKeyWords = command.getSortKeyWords();
		ArrayList<Event> events = data.getArrayList();
		ArrayList<SORT_TYPE> sortKeyTypes = getSortTypeList(sortKeyWords);
		if (sortKeyTypes == null) {
			return new Result(false, null, null, "Unkown sort key words");
		}
		events = sort(events, sortKeyTypes);// sort main tasks;
		for (int i = 0; i < events.size(); i++) {// sort subtasks
			ArrayList<Event> subEvents = events.get(i).getSubTasks();
			subEvents = sort(subEvents, sortKeyTypes);
		}
		Result r = new Result(true, events);
		return r;
	}

	private static ArrayList<SORT_TYPE> getSortTypeList(
			ArrayList<String> sortkeyWords) {
		ArrayList<SORT_TYPE> sortKeyTypes = new ArrayList<SORT_TYPE>();
		if (sortkeyWords == null) {
			return null;
		}
		for (int i = 0; i < sortkeyWords.size(); i++) {
			SORT_TYPE st = SORT_TYPE.determineSortType(sortkeyWords.get(i));
			if (st == SORT_TYPE.INVALID) {
				return null;
			}
			sortKeyTypes.add(st);
		}
		return sortKeyTypes;
	}

	public static ArrayList<Event> sort(ArrayList<Event> events,
			ArrayList<SORT_TYPE> sortTypeList) {
		if (events == null || sortTypeList == null) {
			return null;
		}
		for (int i = 0; i < sortTypeList.size(); i++) {// sort main events
			events = sortBySortType(events, sortTypeList.get(i));
		}
		return events;
	}

	public static ArrayList<Event> sortBySortType(ArrayList<Event> events,
			SORT_TYPE sortKeyWord) {
		// TODO BubbleSort,which is a stable sort!!()
		if (events == null || sortKeyWord == null) {
			return null;
		}

		for (int i = 0; i < events.size() - 1; i++) {
			for (int j = 0; j < events.size() - 1 - i; j++) {
				Event e1 = events.get(j);
				Event e2 = events.get(j + 1);
				int result = Comparer.compareTo(e1, e2, sortKeyWord);
				if (result > 0) {
					swapEvent(j, j + 1, events);
				}
			}
		}
		return events;
	}

	private static ArrayList<Event> swapEvent(int i, int j,
			ArrayList<Event> events) {
		Event temp = events.get(i);
		events.set(i, events.get(j));
		events.set(j, temp);
		return events;
	}

	enum SORT_TYPE {
		START_DATE, END_DATE, PRIORITY, TAG, INVALID;

		static SORT_TYPE determineSortType(String sortKeyWord) {
			// TODO to identify the sort type
			if (sortKeyWord == null)
				throw new Error("command type string cannot be null!");
			if (sortKeyWord.equalsIgnoreCase("startdate")) {
				return SORT_TYPE.START_DATE;
			} else if (sortKeyWord.equalsIgnoreCase("enddate")
					|| sortKeyWord.equalsIgnoreCase("duedate")
					|| sortKeyWord.equalsIgnoreCase("end_date")) {
				return SORT_TYPE.END_DATE;
			} else if (sortKeyWord.equalsIgnoreCase("priority")) {
				return SORT_TYPE.PRIORITY;
			} else if (sortKeyWord.equalsIgnoreCase("tag")) {
				return SORT_TYPE.TAG;
			} else
				return SORT_TYPE.INVALID;
		}
	}

	static class Comparer {
		public static int compareTo(Event e1, Event e2, SORT_TYPE st) {
			switch (st) {
			case START_DATE:
				return e1.getStartDate().compareTo(e2.getStartDate());
			case END_DATE:
				return e1.getEndDate().compareTo(e2.getEndDate());
			case PRIORITY:
				if (e1.getPriority() < e2.getPriority())
					return -1;
				if (e1.getPriority() > e2.getPriority())
					return 1;
				if (e1.getPriority() == e2.getPriority())
					return 0;
			case TAG:
				return e1.getTag().compareTo(e2.getTag());
			case INVALID:
				throw new Error("Unkown sort type");
			default:
				return 0;
			}
		}
	}

	public static void main(String args[]) {
		// TODO test main
		int testSize = 10;
		String sortKeyWord1 = "enddate";
		ArrayList<String> sortKeyWords = new ArrayList<String>();
		sortKeyWords.add(sortKeyWord1);
		// sortKeyWords.add(sortKeyWord2);
		ArrayList<Event> beforeSortList = new ArrayList<Event>();
		for (int i = 0; i < testSize; i++) {
			beforeSortList.add(DummyEventGenerator.getDummyEvent());
		}

		System.out.println("======================");
		System.out.println("EventList before sort");
		System.out.println("======================");
		for (int i = 0; i < testSize; i++) {
			System.out.println(beforeSortList.get(i));
		}
		ArrayList<Event> afterSortList = sort(beforeSortList,
				getSortTypeList(sortKeyWords));
		System.out.println("======================");
		System.out.println("EventList after sort");
		System.out.println("======================");
		if (afterSortList == null) {
			System.out.println("Unkown sort Type");
		} else {
			for (int i = 0; i < testSize; i++) {
				System.out.println(afterSortList.get(i));
			}
		}
	}
}
